// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2024-07-23

package starter

import (
	"context"
	"fmt"
	"gitee.com/go-libs/console"
	"gitee.com/go-wares/framework-iris/framework/src/commands"
	"gitee.com/go-wares/framework-iris/framework/src/conf"
	"os"
)

const (
	Description  = "Start iris application service"
	Name         = "start"
	OptHost      = "host"
	OptHostDesc  = "Service address, e.g. 0.0.0.0"
	OptHostShort = 'h'
	OptPort      = "port"
	OptPortDesc  = "Service listen port, e.g. 8080"
	OptPortShort = 'p'
)

type Command struct {
	commands.Common
	name, desc string
	pid        int
	pidFile    string
	runner     func(ctx context.Context)
}

func (o *Command) Before(_ context.Context, _ *console.Container, command *console.Command) (err error) {
	// Override service address.
	if opt, has := command.GetOption(OptHost); has {
		if str := opt.ToString(); str != "" {
			conf.Config.Host = str
		}
	}

	// Override service port.
	if opt, has := command.GetOption(OptPort); has {
		if n := opt.ToInt(); n > 0 {
			conf.Config.Port = int(n)
		}
	}

	// Extension fields.
	o.pid = os.Getpid()
	o.pidFile = fmt.Sprintf(`%s/%s`, o.PidPath(), o.PidFile())
	return
}

// Run
// starter command.
func (o *Command) Run(ctx context.Context, _ *console.Container, _ *console.Command) (err error) {
	// Start application.
	if o.runner == nil {
		err = fmt.Errorf(`command runner is nil`)
		return
	}

	// call runner.
	o.runner(ctx)
	return
}

// New
// creates a command instance.
func New(runner func(ctx context.Context)) *console.Command {
	var (
		p = &Command{name: Name, desc: Description, runner: runner}
		c = console.NewCommand(p.name).SetDescription(p.desc)
	)

	// Add command options.
	c.Add(
		// Host.
		//
		// -h, --host
		console.NewOption(OptHost).SetDescription(OptHostDesc).
			SetShortName(OptHostShort),

		// Port.
		//
		// -p, --port=8080
		console.NewIntOption(OptPort).SetDescription(OptPortDesc).
			SetShortName(OptPortShort),
	)

	return c.SetProvider(p)
}
